import { FunctionEvent, fromEvent } from 'graphcool-lib'

type User = { id: string }

type Event = FunctionEvent<{
  username: string
  password: string
  name?: string
  role: string
}>

export default async (event: Event) => {
  try {
    const { data } = event
    const graphcool = fromEvent(event)
    const api = graphcool.api('simple/v1')

    {
      data.username = data.username.toLowerCase()

      if (!validateUsername(data.username)) {
        return { error: `invalid username '${data.username}'` }
      }

      if (!validatePassword(data.password)) {
        return { error: 'invalid password' }
      }

      if (!data.name) data.name = data.username
    }

    const mutation = `
      mutation (
        $username: String!
        $password: String!
        $name: String!
        $role: Role!
      ) {
        createUser(
          username: $username
          password: $password
          name: $name
          role: $role
        ) {
          id
        }
      }
    `

    type R = { createUser: User }

    const { createUser: user } = await api.request<R>(mutation, data)

    const token = await graphcool.generateNodeToken(user.id, 'User')

    return { data: { token, userId: user.id } }
  } catch (error) {
    if (error && error.message) {
      if (isUniqueConstraintError(error.message, 'username')) {
        return { error: 'existed username' }
      }
    }
    return { error }
  }
}

const validateUsername = (x: string) => x && /^\w+$/.test(x)

const validatePassword = (x: string) => x && x.length > 7

const isUniqueConstraintError = (message: string, field: string) =>
  message.includes('unique constraint') && message.includes(field)
